import Vue from "vue"
import router from "@/router"
import { axios } from "@/plugins/axios"
import { Token } from "@/store/models/token"
import { User } from "@/store/models/user"
import * as types from "./mutation_types"
import * as usertypes from "../user/mutation_types"

// 存localStorage时加个前缀，防止部署在同一域名但不同前端工程下命名空间冲突
const TOKEN_STORE_NAMESPACE = "fingerprint"

function addLocalStoragePrefix(stor_key) {
  return TOKEN_STORE_NAMESPACE + "/" + stor_key
}

const actions = {
  login({ commit }, data) {
    //  login 相关，获取的是flask-jwt token，同时会设置cookie
    const url = process.env.VUE_APP_API_URL + "auth/login"
    commit(types.AUTH_ERROR_CHANGE, null)
    return axios
      .post(url, data)
      .then((resp) => {
        let data = resp.data
        let token = new Token()
        token.access_token = data.access_token
        token.type = "jwt"
        const exp = Token.decodeExpStampFromJwtToken(token.access_token)
        token.expire_timestamp = exp

        commit(types.AUTH_UPDATE_TOKEN, token)
      })
      .catch((error) => {
        let msg = "登录失败:"
        if (error.response && error.response.status) {
          switch (error.response.status) {
            case 404:
              msg += "未找到该用户"
              break
            case 422:
              msg += "密码错误或者用户不存在"
              break
            case 403:
              msg += "密码错误或者用户不存在"
              break
            case 400:
              msg += "后台服务器错误"
              break
            default:
              msg += "未知错误"
          }
        } else {
          msg += "网络错误"
        }
        commit(types.AUTH_ERROR_CHANGE, msg)
        throw error
      })
  },

  getCaptcha({ commit }){
    // 获取验证码接口
    const url = process.env.VUE_APP_API_URL + "auth/gen_captcha"
    return axios.post(url).then(resp=>{
      return resp.data
    })
  },

  wechat_login({ commit }, auth_code) {
    commit(types.AUTH_ERROR_CHANGE, null)
    const url = process.env.VUE_APP_API_URL + "auth/wechat_login"

    return axios
      .post(url, { code: auth_code })
      .then((resp) => {
        let data = resp.data
        // powerfull almighty for testing purpose
        // data.roles = "almighty";
        let token = new Token()
        token.access_token = data.access_token
        token.type = "jwt"
        const exp = Token.decodeExpStampFromJwtToken(token.access_token)
        token.expire_timestamp = exp

        commit(types.AUTH_UPDATE_TOKEN, token)
      })
      .catch((e) => {
        commit(types.AUTH_ERROR_CHANGE, "登录失败")
        throw e
      })
  },

  logout({ commit }) {
    commit(types.AUTH_RESET)
    commit("user/" + usertypes.CURRENT_USER_RESET, null, {
      root: true,
    })
    router.replace({ name: "SignIn" }).then((_) => {
      Vue.prototype.$dialog.notify.info("退出审图系统，再见~")
      return Promise.resolve(true)
    })
  },
}

function initialState() {
  // localStorage 是key value型，如果直接存个对象可能有问题
  let token = JSON.parse(localStorage.getItem(addLocalStoragePrefix("token")))
  // important, 如果localStorage里面token不存在，获取的token是null的
  // 所以需要下面再初始化字段，避免initialState里不含token字段，导致后续state不响应
  token = Object.assign(new Token(), token)
  return {
    ...token,
    error: null,
  }
}

const state = initialState()

const getters = {
  access_token: (state) =>
    state.access_token && state.access_token.length > 0
      ? state.access_token
      : null, // 放在header里的bearer token
  token: (state) => {
    let token = new Token()
    token.access_token = state.access_token
    token.type = state.type
    token.acquire_timestamp = state.acquire_timestamp
    token.expire_timestamp = state.expire_timestamp
    return token
  },
  error: (state) => state.error, // 登录认证时的错误信息
}

const mutations = {
  [types.AUTH_UPDATE_TOKEN](state, token) {
    localStorage.setItem(addLocalStoragePrefix("token"), JSON.stringify(token))
    state.access_token = token.access_token
    state.type = token.type
    state.acquire_timestamp = token.acquire_timestamp
    state.expire_timestamp = token.expire_timestamp
  },

  [types.AUTH_RESET](state) {
    localStorage.removeItem(addLocalStoragePrefix("token"))

    const s = initialState()
    Object.keys(s).forEach((key) => {
      state[key] = s[key]
    })
  },
  [types.AUTH_ERROR_CHANGE](state, error) {
    state.error = error
  },
}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations,
}
